package com.chukun.reactor.single;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author chukun@meituan.com
 * @version 1.0.0
 * @description reactor
 * @create 2022/1/24 20:09
 **/
public class Reactor implements Runnable {

    private final Selector selector;

    private final ServerSocketChannel serverSocketChannel;

    public Reactor(int port) throws IOException {
        // 创建选择器
        selector = Selector.open();
        // 创建NIO-server
        serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(port));
        serverSocketChannel.configureBlocking(false);
        SelectionKey key = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        // 绑定一个附加对象
        key.attach(new Acceptor(selector, serverSocketChannel));
    }


    @Override
    public void run() {
        while (true) {
            try {
                selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    dispatcher(iterator.next());
                    iterator.remove();
                }
            } catch (Exception e) {
                 e.printStackTrace();
            }
        }
    }

    /**
     * 分发
     * @param key
     */
    private void dispatcher(SelectionKey key) {
        // 调用之前注册时附加的对象，也就是attach附加的acceptor
        Runnable runnable = (Runnable) key.attachment();
        if (runnable != null) {
            runnable.run();
        }
    }

    public static void main(String[] args) throws IOException {
        new Thread(new Reactor(8888)).start();
    }
}
